package cn.iocoder.yudao.module.pay.framework.pay.core;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.common.enums.pay.PayorderDetailStatusEnum;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDetailDO;
import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;

import java.time.LocalDateTime;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;


/**
 * 自定义支付的 PayClient 实现类
 * <p>
 * 需要管理员审核
 *
 * @author jason
 */
public class SpecPayClient extends AbstractPayClient<NonePayClientConfig> {

    public static final String USER_ID_KEY = "user_id";
    public static final String USER_TYPE_KEY = "user_type";

    private static final String SPEC_RESP_SUCCESS_DATA = "SPEC_SUCCESS";

    private PayOrderService orderService;

    public SpecPayClient(Long channelId, NonePayClientConfig config) {
        super(channelId, PayChannelEnum.SPEC.getCode(), config);
    }

    @Override
    protected void doInit() {
        if (orderService == null) {
            orderService = SpringUtil.getBean(PayOrderService.class);
        }
    }

    @Override
    protected PayChannelEnum getChannelEnum() {
        return PayChannelEnum.SPEC;
    }

    @Override
    protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
        if (ObjectUtil.isNull(reqDTO.getPayPicUrl()) || ObjectUtil.isEmpty(reqDTO.getPayPicUrl())) {
            throw exception(new ErrorCode(999999999, "未上传支付图片"));
        }
        Assert.notNull(reqDTO.getCheckResult(), "支付审核结果不能为空");
        if (!reqDTO.getCheckResult()) {
            throw exception(new ErrorCode(999999999, "支付审核不通过"));
        }
        Long userId = MapUtil.getLong(reqDTO.getChannelExtras(), USER_ID_KEY);
        Integer userType = MapUtil.getInt(reqDTO.getChannelExtras(), USER_TYPE_KEY);
        Assert.notNull(userId, "用户 id 不能为空");
        Assert.notNull(userType, "用户类型不能为空");

        if (orderService == null) {
            orderService = SpringUtil.getBean(PayOrderService.class);
        }
        PayOrderDetailDO payDetail = orderService.getOrderDetailByNo(reqDTO.getOutTradeNo());
        Assert.notNull(payDetail, "支付单不存在");
        if (payDetail.getPrice().compareTo(reqDTO.getPrice()) > 0) {
            throw exception(new ErrorCode(999999999, "支付金额不足"));
        }

        return PayOrderRespDTO.successOf(reqDTO.getOutTradeNo(), String.valueOf(userId), LocalDateTime.now(),
                reqDTO.getOutTradeNo(), reqDTO, reqDTO.getPayType());
    }

    @Override
    protected PayOrderRespDTO doGetOrder(String outTradeNo) {
        if (orderService == null) {
            orderService = SpringUtil.getBean(PayOrderService.class);
        }
        PayOrderDetailDO payOrderDetailDO = orderService.getOrderDetailByNo(outTradeNo);
        // 支付交易详情单不存在， 返回关闭状态
        // TODO: 2025/3/22 临时修改
        if (payOrderDetailDO == null) {
            return PayOrderRespDTO.closedOf(String.valueOf(ErrorCodeConstants.PAY_ORDER_DETAIL_NOT_FOUND.getCode()),
                    ErrorCodeConstants.PAY_ORDER_DETAIL_NOT_FOUND.getMsg(), outTradeNo, "", 0);
        }
        // 关闭状态
        if (PayorderDetailStatusEnum.isClosed(payOrderDetailDO.getStatus())) {
            return PayOrderRespDTO.closedOf(
//                    payOrderDetailDO.getChannelErrorCode(),
                    "关闭",
                    "关闭", outTradeNo, "",0);
        }
        // 成功状态
        if (PayorderDetailStatusEnum.SUCCESS.getStatus().equals(payOrderDetailDO.getStatus())) {

            return PayOrderRespDTO.successOf("自定义支付无渠道编号", payOrderDetailDO.getCreator(),
                    payOrderDetailDO.getSuccessTime(), payOrderDetailDO.getOrderNo(), payOrderDetailDO, payOrderDetailDO.getPayType());
        }
        // 其它状态为无效状态
        throw new IllegalStateException(String.format("支付单[%s] 状态不正确", outTradeNo));
    }

    @Override
    protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
        return PayRefundRespDTO.successOf("SPEC-R-" + reqDTO.getOutRefundNo(), LocalDateTime.now(),
                reqDTO.getOutRefundNo(), SPEC_RESP_SUCCESS_DATA);
    }

    // TODO: 2024/7/5 自定义退款
    @Override
    protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) {
        return PayRefundRespDTO.successOf("SPEC-R-" + outRefundNo, LocalDateTime.now(),
                outRefundNo, SPEC_RESP_SUCCESS_DATA);
    }

    @Override
    protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
        throw new UnsupportedOperationException("未实现");
    }

    @Override
    protected PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) {
        throw new UnsupportedOperationException("自定义支付无退款回调");
    }

    @Override
    protected PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) {
        throw new UnsupportedOperationException("自定义支付无支付回调");
    }

    @Override
    protected PayTransferRespDTO doUnifiedTransfer(PayTransferUnifiedReqDTO reqDTO) {
        throw new UnsupportedOperationException("待实现");
    }

    @Override
    protected PayTransferRespDTO doGetTransfer(String outTradeNo, PayTransferTypeEnum type) {
        throw new UnsupportedOperationException("待实现");
    }

}
